from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
import requests
from loguru import logger


@dataclass
class Article:
    """
    Represents an arXiv article with its metadata.
    Attributes:
        id: Unique identifier for the article
        title: Title of the article
        time: Publication time of the article
        authors: List of authors of the article
        summary: Abstract or summary of the article
        pdf_link: URL to the PDF of the article
        pdf_file: Local path to the downloaded PDF file, if available
        ai_summary: AI-generated summary of the article, if available
    """

    id: str
    title: str
    time: str
    authors: list[str]
    summary: str
    pdf_link: str
    pdf_file: Path | None = None
    ai_summary: str | None = None

    @property
    def month_str(self) -> str:
        """Returns the publication month in YYYY-MM format. Used for categorization."""
        try:
            ret = datetime.strptime(self.time, "%Y-%m-%dT%H:%M:%SZ").strftime("%Y-%m")
        except ValueError:
            logger.warning(f"Invalid time format for article {self.id}: {self.time}. Defaulting to 'unknown'")
            ret = "unknown"
        return ret

    def download_pdf(self, output_dir: Path) -> None:
        """
        Downloads the PDF for this article to the specified output directory.
        Args:
            output_dir: The local folder to save the file.
        """
        # Dedicated to downloading PDFs from arXiv
        url = self.pdf_link
        if not url.startswith("http://arxiv.org/pdf/"):
            raise ValueError(f"Invalid arXiv PDF URL: {url}")
        response = requests.get(url, stream=True)
        response.raise_for_status()
        filename = url.split("/")[-1] + ".pdf"
        (output_dir / self.month_str).mkdir(parents=True, exist_ok=True)
        dest_path = output_dir / self.month_str / filename
        if not dest_path.exists():
            with open(dest_path, "wb") as f:
                for chunk in response.iter_content(chunk_size=8192):
                    f.write(chunk)
        self.pdf_file = dest_path.resolve()

    def write_ai_summary(self, output_dir: Path, run_id: str = "") -> None:
        """
        Writes the AI summary to a markdown file in the specified output directory.
        Args:
            output_dir: The local folder to save the markdown file.
            run_id: Unique identifier for the run, used for subdirectory naming.
        """
        if self.ai_summary is None:
            return

        filename = self.pdf_link.split("/")[-1] + ".md"
        (output_dir / run_id).mkdir(parents=True, exist_ok=True)
        dest_path = output_dir / run_id / filename

        with open(dest_path, "w", encoding="utf-8") as f:
            f.write(self.ai_summary)
